package withWaiters;

import java.io.*;
import java.net.*;
import java.util.Random;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;

/**
 * This is a waiter and a philosopher !
 * @author jjeske
 *
 */
public class Philo implements Runnable{
	
	private int id; //id of the philosopher

	private static final int HUNGRY   = 21;
	private static final int EAT 	  = 22;
	private static final int RELFORKS = 23;	
	
	private int timeStamp;
	
	static Logger logger = Logger.getLogger(Philo.class);
	
	public Philo(int id) {
		super();
		this.id = id;
		this.timeStamp = 0;		
		BasicConfigurator.configure(); 
        logger.setLevel(Level.FATAL); 
	}
	
	@Override
	public void run() {
		Random rand = new Random();
		while(true){
			System.out.println("(" + this.id + ", " + this.timeStamp +"): HUNGRY");
			
			getForks();
			
			System.out.println("(" + this.id + ", " + this.timeStamp +"): EATING");
			
			try {
				Thread.sleep((rand.nextInt(5))*1000);
			} catch (InterruptedException e) {
				logger.error(e.getMessage());
			} //eating			
			
			relForks();
			
			System.out.println("(" + this.id + ", " + this.timeStamp +"): THINKING");
			try {
				Thread.sleep((rand.nextInt(5))*1000);
			} catch (InterruptedException e) {
				logger.error(e.getMessage());
			} //thinking();			
		}
		
	}
	
	private void relForks() {
		try {
			Socket canEatClientSocket = new Socket("localhost",6800 + this.id);
			DataOutputStream out = new DataOutputStream(canEatClientSocket.getOutputStream());
			out.writeInt(RELFORKS);
			out.writeInt(777);
			out.close();
			canEatClientSocket.close();
		} catch (UnknownHostException e) {
			logger.error(e.getMessage());
		} catch (IOException e) {
			logger.error(e.getMessage());
		}				
	}
	
	private void getForks() {
		try {
			Socket clientSocket = new Socket("localhost",6000+this.id); //localhost -> porta 6790 + this.id
			DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream());
			out.writeInt(HUNGRY);
			this.timeStamp++;
			out.writeInt(this.timeStamp);
			out.close();
			clientSocket.close();			
		} catch (UnknownHostException e) {
			logger.error(e.getMessage());
		} catch (IOException e) {
			logger.error(e.getMessage());
		}
		
		//Mandou a requesicao para o GArcom, agora fica esperando ate chegar a mensagem de pode comer!
		try {			
			ServerSocket canEatServerSocket = new ServerSocket(6800 + this.id);
			Socket canEatClientSocket = canEatServerSocket.accept();
			DataInputStream in = new DataInputStream(canEatClientSocket.getInputStream());
			int canEatMessage = in.readInt();
			this.timeStamp = Math.max(this.timeStamp, in.readInt());
			logger.info("CanEat: " + canEatMessage + " timestamp: " + this.timeStamp);
			in.close();
			canEatClientSocket.close();
			canEatServerSocket.close();			
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
		
		//PODE COMER!			
	}

}
